UI = {
	playerLoggedIn = false,
	params = setmetatable({}, {
		__index = function (self, k)
			assert(type(k) == "table" and type(k[0]) == "userdata")
			return rawget(self, k[0])
		end,
		__newindex = function (self, k, v)
			assert(type(k) == "table" and type(k[0]) == "userdata")
			rawset(self, k[0], v)
		end,
	}),
	objects = setmetatable({}, {
		__index = function (tbl, key)
			return rawget(tbl, key:lower())
		end,
		__newindex = function (tbl, key, val)
			rawset(tbl, key:lower(), val)
		end,
	}),
	templates = {},
	fonts = {},
}

for _, name in ipairs({
	"base", "constants", "events", "scripts",

	"uiobject", "fontinstance", "region", "lregion", "font", "frame", "texture",
	"worldframe", "button", "slider", "tooltip", "check", "statusbar",
	"scrollframe", "message", "editbox", "cooldown", "fontstring", "smframe",
	"model", "color", "minimap", "pmodel", "tmodel", "dmodel", "taxi", "shtml",
	"movie",

	"animgroup", "anim",

	"api"
}) do
	dofile(string.format("widgets/%s.lua", name))
end

local function GetName(frame, always)
	local name = frame.GetName and frame:GetName()
	if always and not name then
		name = "$parent"
	end
	if name and name:find("$", nil, 1) then
		local parent_name
		local parent = frame:GetParent()
		while parent and not parent_name do
			parent_name = GetName(parent)
			parent = parent:GetParent()
		end
		if not parent_name then
			log("EE Unable to find parent for \"%s\"", name)
			return
		end

		name = name:gsub("$parent", parent_name)
	end
	return name
end

UI.GetName = GetName

local o

function UI.SetGlobal(name, value)
	UI.params[value].name = name
	local new_name = GetName(value)
	if new_name then
		if new_name ~= name then
			UI.params[value].name = new_name
		end
		api.global._G[new_name] = value
	end
	if false and config.DUMP then
		if not o then
			o = io.open("setglobal.log", "w")
		end
		o:write(("%s => %s\n"):format(name, new_name))
	end
end

function UI.GetGlobal(name)
	return api.global._G[name]
end
